package com.cgwx.config;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Aspect
@Component
@Order(1)
@Slf4j
public class AspectConfig {
    @Around("within(com.cgwx.controller.*))")
    public Object around(JoinPoint joinPoint) throws Throwable {
        return aroundExecute(joinPoint);
    }

    public Object aroundExecute(JoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        Object proceed = null;
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            long startTime = System.currentTimeMillis();
            // 打印请求信息
            log.info("HTTP Method: {}\nURL: {}\nRequest Args: {}\n",
                    request.getMethod(), request.getRequestURL().toString(), JSONObject.toJSONString(filterArgs(joinPoint.getArgs())));
            proceed = ((ProceedingJoinPoint) joinPoint).proceed();
            // 检查方法是否带有 @SuppressResponseLog 注解
            boolean shouldSuppressResponseLog = hasSuppressResponseLogAnnotation(joinPoint);
            if (shouldSuppressResponseLog) {
                log.info("Time-Consuming: {}ms\n",
                        System.currentTimeMillis() - startTime);
            } else {
                log.info("Time-Consuming: {}ms\nResponse Args: {}\n",
                        System.currentTimeMillis() - startTime, JSONObject.toJSONString(proceed));
            }
        } else {
            proceed = ((ProceedingJoinPoint) joinPoint).proceed();
        }
        return proceed;
    }

    // 检查目标方法是否应用了 @SuppressResponseLog 注解
    private boolean hasSuppressResponseLogAnnotation(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        return method.isAnnotationPresent(SuppressResponseLog.class);
    }

    private List<Object> filterArgs(Object[] objects) {
        return Arrays.stream(objects).filter(obj -> !(obj instanceof MultipartFile)
                && !(obj instanceof HttpServletResponse)
                && !(obj instanceof HttpServletRequest)).collect(Collectors.toList());
    }
}
